
#include "color.h"

using namespace m3d;

#ifndef min
#define min( a, b ) ( ((a)>(b)) ? (b) : (a) )
#endif 
#ifndef max
#define max( a, b ) ( ((a)<(b)) ? (b) : (a) )
#endif 


// ------------------------------------------ 
SColorF32::SColorF32( void ){}
SColorF32::SColorF32( uint32_t Color )
{
	static float oneOver255 = 1/255.0f;
	r	= ( ((Color & 0x00FF0000L)>>16)*oneOver255 );
	g	= ( ((Color & 0x0000FF00L)>>8)*oneOver255 );
	b	= ( (Color & 0x000000FFL)*oneOver255 );
	a	= ( ((Color & 0xFF000000L)>>24)*oneOver255 );
};

SColorF32::SColorF32( const SColorF32& color )
{
	r=color.r; g=color.g; b=color.b; a=color.a;
};

//SColorF32::SColorF32( float _r, float _g, float _b )
//:r(_r), g(_g), b(_b), a(1.0f) {};
SColorF32::SColorF32( float _r, float _g, float _b, float _a )
{
	r=_r; g=_g; b=_b; a=_a;
};

SColorF32::SColorF32( const float* rgbaColor )
{
	r = rgbaColor[0];
	g = rgbaColor[1];
	b = rgbaColor[2];
	a = rgbaColor[3];
};

bool SColorF32::operator ==( const SColorF32& color ) const
{	// convert to uint32 value to compare with better precision
	return ((SColorI32)*this) == color;
}

bool SColorF32::operator !=( const SColorF32& color ) const
{	// convert to uint32 value to compare with better precision
	return ((SColorI32)*this) != color;
}

// Pack to uint32_t ARGB (stored as B G R A in little-endian systems)
SColorF32::operator uint32_t() const
{
	return (((uint32_t)((a)*255.0f))<<24) | (((uint32_t)((r)*255.0f))<<16) | 
		(((uint32_t)((g)*255.0f))<<8) | ((uint32_t)((b)*255.0f));
}

// Assignment
SColorF32& SColorF32::operator =( const SColorF32& color )
{
	r = color.r;
	g = color.g;
	b = color.b;
	a = color.a;
	return *this;
}
// Component-wise division
SColorF32 SColorF32::operator /( float scalar ) const
{ return SColorF32(r / scalar, g / scalar, b / scalar, a); }
// Scalar muptiplication
SColorF32 SColorF32::operator *( float scalar ) const
{ return SColorF32(min(1.0f,max(0,r * scalar)), min(1.0f,max(0,g * scalar)), min(1.0f,max(0,b * scalar)), a); }
// Scalar multiplication
SColorF32 SColorF32::operator *( double scalar ) const
{ return SColorF32(min(1.0f,max(0,r * (float)scalar)), min(1.0f,max(0,g * (float)scalar)), a ); }// min(1.0f,max(0,b * (float)scalar, a))); }
// Scalar division
SColorF32 SColorF32::operator /( double scalar ) const
{ return SColorF32(r / (float)scalar, g / (float)scalar, b / (float)scalar, a); }
// Component-wise multiplication
SColorF32 SColorF32::operator *( const SColorF32& color ) const
{ return SColorF32(min(1.0f,max(0,r * color.r)), min(1.0f,max(0,g * color.g)), min(1.0f,max(0,b * color.b)), a); }// * color.a); }
// Component-wise addition
SColorF32 SColorF32::operator +( const SColorF32& color ) const
{ return SColorF32(min(1.0f,max(0,r + color.r)), min(1.0f,max(0,g + color.g)), min(1.0f,max(0,b + color.b)), a); }// min(1.0f,max(0,a + color.a))); }

SColorF32& SColorF32::operator *=( float scalar )
{ 
	r *= scalar; g *= scalar; b *= scalar; a;
	r = min(1.0f,max(0,r));
	g = min(1.0f,max(0,g));
	b = min(1.0f,max(0,b));
	return *this;
}

SColorF32& SColorF32::operator *=( double scalar )
{ 
	r *= (float)scalar; g *= (float)scalar; b *= (float)scalar; a;
	r = min(1.0f,max(0,r));
	g = min(1.0f,max(0,g));
	b = min(1.0f,max(0,b));
	return *this;
}

SColorF32& SColorF32::operator /=( float scalar )
{ 
	r /= scalar; g /= scalar; b /= scalar; a;
	r = min(1.0f,max(0,r));
	g = min(1.0f,max(0,g));
	b = min(1.0f,max(0,b));
	return *this;
}

SColorF32& SColorF32::operator /=( double scalar )
{ 
	r /= (float)scalar; g /= (float)scalar; b /= (float)scalar; a;
	r = min(1.0f,max(0,r));
	g = min(1.0f,max(0,g));
	b = min(1.0f,max(0,b));
	return *this;
}


SColorF32& SColorF32::operator +=( const SColorF32& color )
{ 
	r += color.r; g += color.g; b += color.b; a;
	r = min(1.0f,max(0,r));
	g = min(1.0f,max(0,g));
	b = min(1.0f,max(0,b));

	return *this;
}
